package com.mdd.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mdd.common.BaseContext;
import com.mdd.common.CustomException;
import com.mdd.common.R;
import com.mdd.mapper.UserMapper;
import com.mdd.pojo.User;
import com.mdd.pojo.request.VoucherOrderAddRequest;
import com.mdd.pojo.vo.SignVo;
import com.mdd.pojo.vo.UserVo;
import com.mdd.service.UserService;
import com.mdd.service.VoucherOrderService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private VoucherOrderService voucherOrderService;

    @Override
    public UserVo getUserVo(User user) {
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);
        return userVo;
    }

    @Override
    public boolean userSign() {
        //获取当前登录用户
        Long currentId = BaseContext.getCurrentId();
        //获取当前时间
        LocalDate now = LocalDate.now();
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyy:MM"));
        String key = "sign:"+currentId+keySuffix;
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        //签到
        int dayOfMonth = now.getDayOfMonth();
        Boolean aBoolean = opsForValue.setBit(key, dayOfMonth-1, true);
        Boolean aBoolean1 = opsForValue.setBit(key, dayOfMonth-1, true);
        return Boolean.TRUE.equals(aBoolean1);
    }

    @Override
    public R<SignVo> signCount() {
//        获取当前登录用户id5
        Long currentId = BaseContext.getCurrentId();
//        获取日期
        LocalDate now = LocalDate.now();
//        拼接得到key
        String suffix = now.format(DateTimeFormatter.ofPattern(":yyyy:MM"));
        String key = "sign:"+currentId+suffix;
//        获取当前是本月第几天
        int dayOfMonth = now.getDayOfMonth();
//        获取本月截至今天为止的所有签到记录返回一个十进制数字
        List<Long> longs = redisTemplate.opsForValue().bitField(
                key,
                BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
        SignVo signVo = new SignVo();
        if (longs == null||longs.isEmpty()) {
            //说明当前用户本月还没有签过到
            signVo.setSignSum(0);
            signVo.setContinuousSign(0);
            return R.success(signVo);
        }
        Long aLong = longs.get(0);
        if (aLong == null || aLong == 0) {
            //说明当前用户本月还没有签过到
            signVo.setSignSum(0);
            signVo.setContinuousSign(0);
            return R.success(signVo);
        }
//        设计算法通过算法循环遍历这个十进制数字得到连续签到次数和总签到次数
        //计算连续签到次数
        int count = 0;
        long temp = aLong;
        while (true) {
            //说明没有签到，退出循环
            if ((temp & 1) == 0) {
                break;
            }else {
                //说明签到了
                count++;
            }
            //把数字右移一位
            temp>>>=1;
        }
        signVo.setContinuousSign(count);
        //计算总签到次数
        int sum = 0;
        while (aLong > 0) {
            if ((aLong & 1) == 1) {
                sum++;
            }
            aLong>>=1;
        }
        signVo.setSignSum(sum);
        //如果连续签到三天送一张优惠券
        if (count % 3 == 0) {
            VoucherOrderAddRequest voucherOrderAddRequest = new VoucherOrderAddRequest();
            voucherOrderAddRequest.setUserId(currentId);
            voucherOrderAddRequest.setVoucherId(15L);
            R<Long> voucherOrder = voucherOrderService.createVoucherOrder(voucherOrderAddRequest);
            if (voucherOrder.getData() == null || voucherOrder.getData() <= 0) {
                throw new CustomException("优惠券赠送有误");
            }
            signVo.setVoucherName("优享券");
        }
        return R.success(signVo);
    }
}
